<!DOCTYPE html>



  


<html class="theme-next pisces use-motion" lang="zh-CN">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.3" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png?v=5.1.3">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png?v=5.1.3">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png?v=5.1.3">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.3" color="#222">





  <meta name="keywords" content="python," />




  


  <link rel="alternate" href="/atom.xml" title="理想-咸鱼" type="application/atom+xml" />






<meta name="description" content="python setup.py 浅析setuptools.setup() 参数说明packages对于所有 packages 列表里提到的纯 Python 模块做处理需要在 setup 脚本里有一个包名到目录的映射。默认对于 setup 脚本所在目录下同名的目录即视为包所在目录。当你在 setup 脚本中写入 packages &#x3D; [‘foo’] 时， setup 脚本的同级目录下可以找到 foo">
<meta property="og:type" content="article">
<meta property="og:title" content="python setup.py 浅析">
<meta property="og:url" content="http://yoursite.com/2018/11/16/python-setup.py--qian-xi/index.html">
<meta property="og:site_name" content="理想-咸鱼">
<meta property="og:description" content="python setup.py 浅析setuptools.setup() 参数说明packages对于所有 packages 列表里提到的纯 Python 模块做处理需要在 setup 脚本里有一个包名到目录的映射。默认对于 setup 脚本所在目录下同名的目录即视为包所在目录。当你在 setup 脚本中写入 packages &#x3D; [‘foo’] 时， setup 脚本的同级目录下可以找到 foo">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2018-11-16T06:02:43.000Z">
<meta property="article:modified_time" content="2018-11-28T05:36:36.000Z">
<meta property="article:author" content="bigfish">
<meta property="article:tag" content="python">
<meta name="twitter:card" content="summary">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    version: '5.1.3',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: 'Author'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://yoursite.com/2018/11/16/python-setup.py--qian-xi/"/>





  <title>python setup.py 浅析 | 理想-咸鱼</title>
  








<meta name="generator" content="Hexo 4.2.0"></head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">理想-咸鱼</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle">鱼翔浅底</p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            Archives
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            Tags
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            Categories
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2018/11/16/python-setup.py--qian-xi/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="bigfish">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="理想-咸鱼">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">python setup.py 浅析</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2018-11-16T14:02:43+08:00">
                2018-11-16
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          
            <span class="post-meta-divider">|</span>
            <span class="page-pv"><i class="fa fa-file-o"></i>  阅读数
            <span class="busuanzi-value" id="busuanzi_value_page_pv" ></span>
            </span>
          

          
            <div class="post-wordcount">
              
                
                <span class="post-meta-item-icon">
                  <i class="fa fa-file-word-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Words count in article&#58;</span>
                
                <span title="Words count in article">
                  2.1k
                </span>
              

              
                <span class="post-meta-divider">|</span>
              

              
                <span class="post-meta-item-icon">
                  <i class="fa fa-clock-o"></i>
                </span>
                
                  <span class="post-meta-item-text">Reading time &asymp;</span>
                
                <span title="Reading time">
                  10
                </span>
              
            </div>
          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1 id="python-setup-py-浅析"><a href="#python-setup-py-浅析" class="headerlink" title="python setup.py 浅析"></a>python setup.py 浅析</h1><h2 id="setuptools-setup-参数说明"><a href="#setuptools-setup-参数说明" class="headerlink" title="setuptools.setup() 参数说明"></a>setuptools.setup() 参数说明</h2><h3 id="packages"><a href="#packages" class="headerlink" title="packages"></a>packages</h3><p>对于所有 packages 列表里提到的纯 Python 模块做处理<br>需要在 setup 脚本里有一个包名到目录的映射。<br>默认对于 setup 脚本所在目录下同名的目录即视为包所在目录。<br>当你在 setup 脚本中写入 packages = [‘foo’] 时， setup 脚本的同级目录下可以找到 <code>foo/__init__.py</code>。如果没有找到对应文件，disutils 不会直接报错，而是给出一个告警然后继续进行有问题的打包流程。</p>
<h3 id="package-dir"><a href="#package-dir" class="headerlink" title="package_dir"></a>package_dir</h3><p>阐明包名到目录的映射，见 packages</p>
<pre><code>package_dir = {&apos;&apos;: &apos;lib&apos;}</code></pre><p>键: 代表了包的名字，空的包名则代表 root package(不在任何包中的顶层包)。<br>值: 代表了对于 setup 脚本所在目录的相对路径.</p>
<pre><code>packages = [&apos;foo&apos;]
package_dir = {&apos;&apos;: &apos;lib&apos;}</code></pre><p>指明包位于 lib/foo/, <code>lib/foo/__init__.py</code> 这个文件存在</p>
<p>另一种方法则是直接将 foo 这个包的内容全部放入 lib 而不是在 lib 下建一个 foo 目录</p>
<pre><code>package_dir = {&apos;foo&apos;: &apos;lib&apos;}</code></pre><p>一个在 package_dir 字典中的 package: dir 映射会对当前包下的所有包都生效， 所以 foo.bar 会自动生效. 在这个例子当中， <code>packages = [&#39;foo&#39;, &#39;foo.bar&#39;]</code> 告诉 distutils 去寻找 <code>lib/__init__.py</code> 和 <code>lib/bar/__init__.py</code>.</p>
<h3 id="py-modules"><a href="#py-modules" class="headerlink" title="py_modules"></a>py_modules</h3><p>对于一个相对较小的模块的发布，你可能更想要列出所有模块而不是列出所有的包，尤其是对于那种根目录下就是一个简单模块的类型.<br>这描述了两个包，一个在根目录下，另一个则在 pkg 目录下。<br>默认的 “包：目录” 映射关系表明你可以在 setup 脚本所在的路径下找到 mod1.py 和 pkg/mod2.py。<br>当然，你也可以用 package_dir 选项重写这层映射关系就是了。</p>
<h3 id="find-packages"><a href="#find-packages" class="headerlink" title="find_packages"></a>find_packages</h3><p>packages=find_packages(exclude=(‘tests’, ‘robot_server.scripts’)),<br>exclude 里面是包名，而非路径</p>
<h3 id="include-package-data"><a href="#include-package-data" class="headerlink" title="include_package_data"></a>include_package_data</h3><p>引入包内的非 Python 文件<br>include_package_data 需要配合 MANIFEST.in 一起使用</p>
<p>MANIFEST.in:</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">include myapp/scripts/start.py</span><br><span class="line">recursive-include myapp/static *</span><br></pre></td></tr></table></figure>

<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">setup(</span><br><span class="line">    name=<span class="string">'MyApp'</span>,         <span class="comment"># 应用名</span></span><br><span class="line">    version=<span class="string">'1.0'</span>,        <span class="comment"># 版本号</span></span><br><span class="line">    packages=[<span class="string">'myapp'</span>],   <span class="comment"># 包括在安装包内的Python包</span></span><br><span class="line">    include_package_data=<span class="literal">True</span>    <span class="comment"># 启用清单文件MANIFEST.in</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure>

<p>注意，此处引入或者排除的文件必须是 package 内的文件</p>
<pre><code>setup-demo/
  ├ mydata.data      # 数据文件
  ├ setup.py         # 安装文件
  ├ MANIFEST.in      # 清单文件
  └ myapp/           # 源代码
      ├ static/      # 静态文件目录
      ├ __init__.py
      ...</code></pre><p>在 MANIFEST.in 引入 include mydata.data 将不起作用</p>
<h3 id="exclude-package-date"><a href="#exclude-package-date" class="headerlink" title="exclude_package_date"></a>exclude_package_date</h3><p>排除一部分包文件<br>{‘myapp’:[‘.gitignore]}，就表明只排除 myapp 包下的所有. gitignore 文件。</p>
<h3 id="data-files"><a href="#data-files" class="headerlink" title="data_files"></a>data_files</h3><p>指定其他的一些文件（如配置文件）</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">data_files=[(<span class="string">'bitmaps'</span>, [<span class="string">'bm/b1.gif'</span>, <span class="string">'bm/b2.gif'</span>]),</span><br><span class="line">            (<span class="string">'config'</span>, [<span class="string">'cfg/data.cfg'</span>]),</span><br><span class="line">            (<span class="string">'/etc/init.d'</span>, [<span class="string">'init-script'</span>])]</span><br></pre></td></tr></table></figure>

<p>规定了哪些文件被安装到哪些目录中。<br>如果目录名是相对路径 (比如 bitmaps)，则是相对于 sys.prefix(/usr) 或 sys.exec_prefix 的路径。<br>否则安装到绝对路径 (比如 /etc/init.d)。</p>
<h3 id="cmdclass"><a href="#cmdclass" class="headerlink" title="cmdclass"></a>cmdclass</h3><p>定制化命令，通过继承 setuptools.command 下的命令类来进行定制化</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UploadCommand</span><span class="params">(Command)</span>:</span></span><br><span class="line">    <span class="string">"""Support setup.py upload."""</span></span><br><span class="line">    ...</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            self.status(<span class="string">'Removing previous builds…'</span>)</span><br><span class="line">            rmtree(os.path.join(here, <span class="string">'dist'</span>))</span><br><span class="line">        <span class="keyword">except</span> OSError:</span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">        self.status(<span class="string">'Building Source and Wheel (universal) distribution…'</span>)</span><br><span class="line">        os.system(<span class="string">'&#123;0&#125; setup.py sdist bdist_wheel --universal'</span>.format(sys.executable))</span><br><span class="line"></span><br><span class="line">        self.status(<span class="string">'Uploading the package to PyPI via Twine…'</span>)</span><br><span class="line">        os.system(<span class="string">'twine upload dist/*'</span>)</span><br><span class="line"></span><br><span class="line">        self.status(<span class="string">'Pushing git tags…'</span>)</span><br><span class="line">        os.system(<span class="string">'git tag v&#123;0&#125;'</span>.format(about[<span class="string">'__version__'</span>]))</span><br><span class="line">        os.system(<span class="string">'git push --tags'</span>)</span><br><span class="line"></span><br><span class="line">        sys.exit()</span><br><span class="line"></span><br><span class="line">setup(</span><br><span class="line">    ...</span><br><span class="line">    <span class="comment"># $ setup.py publish support.</span></span><br><span class="line">    cmdclass=&#123;</span><br><span class="line">        <span class="string">'upload'</span>: UploadCommand,</span><br><span class="line">    &#125;,</span><br><span class="line">)</span><br></pre></td></tr></table></figure>

<p>这样可以通过 <code>python setup.py upload</code> 运行打包上传代码</p>
<h3 id="install-requires"><a href="#install-requires" class="headerlink" title="install_requires"></a>install_requires</h3><p>安装这个包所需要的依赖，列表</p>
<h3 id="tests-require"><a href="#tests-require" class="headerlink" title="tests_require"></a>tests_require</h3><p>与 install_requires 作用相似，单元测试时所需要的依赖</p>
<h2 id="虚拟运行环境下安装包"><a href="#虚拟运行环境下安装包" class="headerlink" title="虚拟运行环境下安装包"></a>虚拟运行环境下安装包</h2><p>以 <a href="https://github.com/kennethreitz/legit" target="_blank" rel="noopener">legit</a> 为例</p>
<ul>
<li><p>下载 lgit 源码<br><code>git clone https://github.com/kennethreitz/legit.git</code></p>
</li>
<li><p>创建虚拟运行环境<br><code>virtualenv --no-site-packages venv</code><br>运行环境目录结构为：</p>
<pre><code>venv/
├── bin
├── include
├── lib
├── local
└── pip-selfcheck.json</code></pre></li>
<li><p>打包工程<br><code>python3 setup.py sdist bdist_wheel</code></p>
<pre><code>.
├── AUTHORS
├── build
│   ├── bdist.linux-x86_64
│   └── lib.linux-x86_64-2.7
├── dist
│   ├── legit-1.0.1-py2.py3-none-any.whl
│   └── legit-1.0.1.tar.gz</code></pre><p>在 dist 下生成了安装包</p>
</li>
<li><p>进入虚拟环境<br><code>source venv/bin/activate</code></p>
</li>
<li><p>安装包<br> <code>pip install ./dist/legit-1.0.1.tar.gz</code></p>
<pre><code>Successfully built legit args clint
Installing collected packages: appdirs, args, click, lint, colorama, crayons, smmap2, gitdb2, GitPython, ix, pyparsing, packaging, legit
Successfully installed GitPython-2.1.8 appdirs-1.4.3 rgs-0.1.0 click-6.7 clint-0.5.1 colorama-0.4.0 rayons-0.1.2 gitdb2-2.0.3 legit-1.0.1 packaging-17.1 yparsing-2.2.0 six-1.11.0 smmap2-2.0.3</code></pre></li>
</ul>
<h2 id="安装过程分析"><a href="#安装过程分析" class="headerlink" title="安装过程分析"></a>安装过程分析</h2><p><code>venv/lib/python2.7/site-packages/</code> 下安装了 legit 及依赖包</p>
<pre><code>legit/venv/lib/python2.7/site-packages$ tree -L 1

.
├── appdirs-1.4.3.dist-info
├── appdirs.py
├── appdirs.pyc
├── args-0.1.0.dist-info
├── args.py
├── args.pyc
├── click
├── click-6.7.dist-info
├── clint
├── clint-0.5.1.dist-info
├── colorama
├── colorama-0.4.0.dist-info
├── crayons-0.1.2.dist-info
├── crayons.py
├── crayons.pyc
├── easy_install.py
├── easy_install.pyc
├── git
├── gitdb
├── gitdb2-2.0.3.dist-info
├── GitPython-2.1.8.dist-info
├── legit
├── legit-1.0.1.dist-info
├── packaging
├── packaging-17.1.dist-info
├── pip
├── pip-18.1.dist-info
├── pkg_resources
├── pyparsing-2.2.0.dist-info
├── pyparsing.py
├── pyparsing.pyc
├── setuptools
├── setuptools-40.6.2.dist-info
├── six-1.11.0.dist-info
├── six.py
├── six.pyc
├── smmap
├── smmap2-2.0.3.dist-info
├── wheel
└── wheel-0.32.2.dist-info</code></pre><p><code>venv/bin</code> 下新增可执行文件 legit, 内容为</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/home/turtlebot/learn/python/legit/venv/bin/python</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> legit.cli <span class="keyword">import</span> cli</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    sys.argv[<span class="number">0</span>] = re.sub(<span class="string">r'(-script\.pyw?|\.exe)?$'</span>, <span class="string">''</span>, sys.argv[<span class="number">0</span>])</span><br><span class="line">    sys.exit(cli())</span><br></pre></td></tr></table></figure>

<p>此时，可以直接运行</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&gt;&gt;&gt; legit</span><br></pre></td></tr></table></figure>

<h2 id="setup-py-分析"><a href="#setup-py-分析" class="headerlink" title="setup.py 分析"></a>setup.py 分析</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> codecs <span class="keyword">import</span> open  <span class="comment"># To use a consistent encoding</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> setuptools <span class="keyword">import</span> setup  <span class="comment"># Always prefer setuptools over distutils</span></span><br><span class="line"></span><br><span class="line">APP_NAME = <span class="string">'legit'</span></span><br><span class="line">APP_SCRIPT = <span class="string">'./legit_r'</span></span><br><span class="line">VERSION = <span class="string">'1.0.1'</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># Grab requirements.</span></span><br><span class="line"><span class="keyword">with</span> open(<span class="string">'reqs.txt'</span>) <span class="keyword">as</span> f:</span><br><span class="line">    required = f.readlines()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">settings = dict()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># Publish Helper.</span></span><br><span class="line"><span class="keyword">if</span> sys.argv[<span class="number">-1</span>] == <span class="string">'publish'</span>:</span><br><span class="line">    os.system(<span class="string">'python setup.py sdist bdist_wheel upload'</span>)</span><br><span class="line">    sys.exit()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> sys.argv[<span class="number">-1</span>] == <span class="string">'build_manpage'</span>:</span><br><span class="line">    os.system(<span class="string">'rst2man.py README.rst &gt; extra/man/legit.1'</span>)</span><br><span class="line">    sys.exit()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># Build Helper.</span></span><br><span class="line"><span class="keyword">if</span> sys.argv[<span class="number">-1</span>] == <span class="string">'build'</span>:</span><br><span class="line">    <span class="keyword">import</span> py2exe  <span class="comment"># noqa</span></span><br><span class="line">    sys.argv.append(<span class="string">'py2exe'</span>)</span><br><span class="line"></span><br><span class="line">    settings.update(</span><br><span class="line">        console=[&#123;<span class="string">'script'</span>: APP_SCRIPT&#125;],</span><br><span class="line">        zipfile=<span class="literal">None</span>,</span><br><span class="line">        options=&#123;</span><br><span class="line">            <span class="string">'py2exe'</span>: &#123;</span><br><span class="line">                <span class="string">'compressed'</span>: <span class="number">1</span>,</span><br><span class="line">                <span class="string">'optimize'</span>: <span class="number">0</span>,</span><br><span class="line">                <span class="string">'bundle_files'</span>: <span class="number">1</span>&#125;&#125;)</span><br><span class="line"></span><br><span class="line">settings.update(</span><br><span class="line">    name=APP_NAME,</span><br><span class="line">    version=VERSION,</span><br><span class="line">    description=<span class="string">'Git for Humans.'</span>,</span><br><span class="line">    long_description=open(<span class="string">'README.rst'</span>).read(),</span><br><span class="line">    author=<span class="string">'Kenneth Reitz'</span>,</span><br><span class="line">    author_email=<span class="string">'me@kennethreitz.com'</span>,</span><br><span class="line">    url=<span class="string">'https://github.com/kennethreitz/legit'</span>,</span><br><span class="line">    packages=[<span class="string">'legit'</span>],</span><br><span class="line">    install_requires=required,</span><br><span class="line">    license=<span class="string">'BSD'</span>,</span><br><span class="line">    classifiers=[</span><br><span class="line">        <span class="string">'Development Status :: 5 - Production/Stable'</span>,</span><br><span class="line">        <span class="string">'Intended Audience :: Developers'</span>,</span><br><span class="line">        <span class="string">'Natural Language :: English'</span>,</span><br><span class="line">        <span class="string">'License :: OSI Approved :: BSD License'</span>,</span><br><span class="line">        <span class="string">'Programming Language :: Python'</span>,</span><br><span class="line">        <span class="string">'Programming Language :: Python :: 2'</span>,</span><br><span class="line">        <span class="string">'Programming Language :: Python :: 2.7'</span>,</span><br><span class="line">        <span class="string">'Programming Language :: Python :: 3'</span>,</span><br><span class="line">        <span class="string">'Programming Language :: Python :: 3.4'</span>,</span><br><span class="line">        <span class="string">'Programming Language :: Python :: 3.5'</span>,</span><br><span class="line">        <span class="string">'Programming Language :: Python :: 3.6'</span>,</span><br><span class="line">    ],</span><br><span class="line">    entry_points=&#123;</span><br><span class="line">        <span class="string">'console_scripts'</span>: [</span><br><span class="line">            <span class="string">'legit = legit.cli:cli'</span>,</span><br><span class="line">        ],</span><br><span class="line">    &#125;</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">setup(**settings)</span><br></pre></td></tr></table></figure>

<ul>
<li>packages=[‘legit’] 引入 legit 目录下的所有默认引入文件</li>
<li>install_requires=required 指明安装时需要额外安装的第三方库</li>
<li><code>&#39;console_scripts&#39;: [&#39;legit = legit.cli:cli&#39;,]</code> 生成可执行控制台程序，程序名为 legit, 运行 legit.cli 中的 cli() 函数。最终会在 bin/ 下生成 legit 可执行 py 文件，调用制定的函数</li>
</ul>
<h2 id="setup-py-实例分析"><a href="#setup-py-实例分析" class="headerlink" title="setup.py 实例分析"></a>setup.py 实例分析</h2><p><a href="https://github.com/kennethreitz/setup.py" target="_blank" rel="noopener">kennethreitz/setup.py</a></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Note: To use the 'upload' functionality of this file, you must:</span></span><br><span class="line"><span class="comment">#   $ pip install twine</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> io</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> shutil <span class="keyword">import</span> rmtree</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> setuptools <span class="keyword">import</span> find_packages, setup, Command</span><br><span class="line"></span><br><span class="line"><span class="comment"># Package meta-data.</span></span><br><span class="line">NAME = <span class="string">'mypackage'</span></span><br><span class="line">DESCRIPTION = <span class="string">'My short description for my project.'</span></span><br><span class="line">URL = <span class="string">'https://github.com/me/myproject'</span></span><br><span class="line">EMAIL = <span class="string">'me@example.com'</span></span><br><span class="line">AUTHOR = <span class="string">'Awesome Soul'</span></span><br><span class="line">REQUIRES_PYTHON = <span class="string">'&gt;=3.6.0'</span></span><br><span class="line">VERSION = <span class="literal">None</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># What packages are required for this module to be executed?</span></span><br><span class="line">REQUIRED = [</span><br><span class="line">    <span class="comment"># 'requests', 'maya', 'records',</span></span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"><span class="comment"># What packages are optional?</span></span><br><span class="line">EXTRAS = &#123;</span><br><span class="line">    <span class="comment"># 'fancy feature': ['django'],</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># The rest you shouldn't have to touch too much :)</span></span><br><span class="line"><span class="comment"># ------------------------------------------------</span></span><br><span class="line"><span class="comment"># Except, perhaps the License and Trove Classifiers!</span></span><br><span class="line"><span class="comment"># If you do change the License, remember to change the Trove Classifier for that!</span></span><br><span class="line"></span><br><span class="line">here = os.path.abspath(os.path.dirname(__file__))</span><br><span class="line"></span><br><span class="line"><span class="comment"># Import the README and use it as the long-description.</span></span><br><span class="line"><span class="comment"># Note: this will only work if 'README.md' is present in your MANIFEST.in file!</span></span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line">    <span class="keyword">with</span> io.open(os.path.join(here, <span class="string">'README.md'</span>), encoding=<span class="string">'utf-8'</span>) <span class="keyword">as</span> f:</span><br><span class="line">        long_description = <span class="string">'\n'</span> + f.read()</span><br><span class="line"><span class="keyword">except</span> FileNotFoundError:</span><br><span class="line">    long_description = DESCRIPTION</span><br><span class="line"></span><br><span class="line"><span class="comment"># Load the package's __version__.py module as a dictionary.</span></span><br><span class="line">about = &#123;&#125;</span><br><span class="line"><span class="keyword">if</span> <span class="keyword">not</span> VERSION:</span><br><span class="line">    <span class="keyword">with</span> open(os.path.join(here, NAME, <span class="string">'__version__.py'</span>)) <span class="keyword">as</span> f:</span><br><span class="line">        exec(f.read(), about)</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">    about[<span class="string">'__version__'</span>] = VERSION</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UploadCommand</span><span class="params">(Command)</span>:</span></span><br><span class="line">    <span class="string">"""Support setup.py upload."""</span></span><br><span class="line"></span><br><span class="line">    description = <span class="string">'Build and publish the package.'</span></span><br><span class="line">    user_options = []</span><br><span class="line"></span><br><span class="line"><span class="meta">    @staticmethod</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">status</span><span class="params">(s)</span>:</span></span><br><span class="line">        <span class="string">"""Prints things in bold."""</span></span><br><span class="line">        print(<span class="string">'\033[1m&#123;0&#125;\033[0m'</span>.format(s))</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">initialize_options</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">finalize_options</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            self.status(<span class="string">'Removing previous builds…'</span>)</span><br><span class="line">            rmtree(os.path.join(here, <span class="string">'dist'</span>))</span><br><span class="line">        <span class="keyword">except</span> OSError:</span><br><span class="line">            <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">        self.status(<span class="string">'Building Source and Wheel (universal) distribution…'</span>)</span><br><span class="line">        os.system(<span class="string">'&#123;0&#125; setup.py sdist bdist_wheel --universal'</span>.format(sys.executable))</span><br><span class="line"></span><br><span class="line">        self.status(<span class="string">'Uploading the package to PyPI via Twine…'</span>)</span><br><span class="line">        os.system(<span class="string">'twine upload dist/*'</span>)</span><br><span class="line"></span><br><span class="line">        self.status(<span class="string">'Pushing git tags…'</span>)</span><br><span class="line">        os.system(<span class="string">'git tag v&#123;0&#125;'</span>.format(about[<span class="string">'__version__'</span>]))</span><br><span class="line">        os.system(<span class="string">'git push --tags'</span>)</span><br><span class="line"></span><br><span class="line">        sys.exit()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># Where the magic happens:</span></span><br><span class="line">setup(</span><br><span class="line">    name=NAME,</span><br><span class="line">    version=about[<span class="string">'__version__'</span>],</span><br><span class="line">    description=DESCRIPTION,</span><br><span class="line">    long_description=long_description,</span><br><span class="line">    long_description_content_type=<span class="string">'text/markdown'</span>,</span><br><span class="line">    author=AUTHOR,</span><br><span class="line">    author_email=EMAIL,</span><br><span class="line">    python_requires=REQUIRES_PYTHON,</span><br><span class="line">    url=URL,</span><br><span class="line">    packages=find_packages(exclude=(<span class="string">'tests'</span>,)),</span><br><span class="line">    <span class="comment"># If your package is a single module, use this instead of 'packages':</span></span><br><span class="line">    <span class="comment"># py_modules=['mypackage'],</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># entry_points=&#123;</span></span><br><span class="line">    <span class="comment">#     'console_scripts': ['mycli=mymodule:cli'],</span></span><br><span class="line">    <span class="comment"># &#125;,</span></span><br><span class="line">    install_requires=REQUIRED,</span><br><span class="line">    extras_require=EXTRAS,</span><br><span class="line">    include_package_data=<span class="literal">True</span>,</span><br><span class="line">    license=<span class="string">'MIT'</span>,</span><br><span class="line">    classifiers=[</span><br><span class="line">        <span class="comment"># Trove classifiers</span></span><br><span class="line">        <span class="comment"># Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers</span></span><br><span class="line">        <span class="string">'License :: OSI Approved :: MIT License'</span>,</span><br><span class="line">        <span class="string">'Programming Language :: Python'</span>,</span><br><span class="line">        <span class="string">'Programming Language :: Python :: 3'</span>,</span><br><span class="line">        <span class="string">'Programming Language :: Python :: 3.6'</span>,</span><br><span class="line">        <span class="string">'Programming Language :: Python :: Implementation :: CPython'</span>,</span><br><span class="line">        <span class="string">'Programming Language :: Python :: Implementation :: PyPy'</span></span><br><span class="line">    ],</span><br><span class="line">    <span class="comment"># $ setup.py publish support.</span></span><br><span class="line">    cmdclass=&#123;</span><br><span class="line">        <span class="string">'upload'</span>: UploadCommand,</span><br><span class="line">    &#125;,</span><br><span class="line">)</span><br></pre></td></tr></table></figure>


<hr>
<p>Sync From: <a href="https://github.com/TheBigFish/blog/issues/6" target="_blank" rel="noopener">https://github.com/TheBigFish/blog/issues/6</a></p>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/python/" rel="tag"># python</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2018/11/15/python--duo-xian-cheng-bian-cheng/" rel="next" title="python 多线程编程">
                <i class="fa fa-chevron-left"></i> python 多线程编程
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2018/11/29/python-decorators/" rel="prev" title="python decorators">
                python decorators <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          
  
    <div id="gitalk-container"></div>
  


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            Table of Contents
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            Overview
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <p class="site-author-name" itemprop="name">bigfish</p>
              <p class="site-description motion-element" itemprop="description">一些简单的想法</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/%7C%7C%20archive">
              
                  <span class="site-state-item-count">18</span>
                  <span class="site-state-item-name">posts</span>
                </a>
              </div>
            

            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">5</span>
                  <span class="site-state-item-name">tags</span>
                </a>
              </div>
            

          </nav>

          
            <div class="feed-link motion-element">
              <a href="/atom.xml" rel="alternate">
                <i class="fa fa-rss"></i>
                RSS
              </a>
            </div>
          

          <div class="links-of-author motion-element">
            
          </div>

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#python-setup-py-浅析"><span class="nav-number">1.</span> <span class="nav-text">python setup.py 浅析</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#setuptools-setup-参数说明"><span class="nav-number">1.1.</span> <span class="nav-text">setuptools.setup() 参数说明</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#packages"><span class="nav-number">1.1.1.</span> <span class="nav-text">packages</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#package-dir"><span class="nav-number">1.1.2.</span> <span class="nav-text">package_dir</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#py-modules"><span class="nav-number">1.1.3.</span> <span class="nav-text">py_modules</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#find-packages"><span class="nav-number">1.1.4.</span> <span class="nav-text">find_packages</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#include-package-data"><span class="nav-number">1.1.5.</span> <span class="nav-text">include_package_data</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#exclude-package-date"><span class="nav-number">1.1.6.</span> <span class="nav-text">exclude_package_date</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#data-files"><span class="nav-number">1.1.7.</span> <span class="nav-text">data_files</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#cmdclass"><span class="nav-number">1.1.8.</span> <span class="nav-text">cmdclass</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#install-requires"><span class="nav-number">1.1.9.</span> <span class="nav-text">install_requires</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#tests-require"><span class="nav-number">1.1.10.</span> <span class="nav-text">tests_require</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#虚拟运行环境下安装包"><span class="nav-number">1.2.</span> <span class="nav-text">虚拟运行环境下安装包</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#安装过程分析"><span class="nav-number">1.3.</span> <span class="nav-text">安装过程分析</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#setup-py-分析"><span class="nav-number">1.4.</span> <span class="nav-text">setup.py 分析</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#setup-py-实例分析"><span class="nav-number">1.5.</span> <span class="nav-text">setup.py 实例分析</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">bigfish</span>

  
</div>


  <div class="powered-by">Powered by <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a></div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">Theme &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Pisces</a> v5.1.3</div>




<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>




        
<div class="busuanzi-count">
  <script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>

  
    <span class="site-uv">
      访客数
      <span class="busuanzi-value" id="busuanzi_value_site_uv"></span>
      人
    </span>
  

  
    <span class="site-pv">
      总访问量
      <span class="busuanzi-value" id="busuanzi_value_site_pv"></span>
      次
    </span>
  
</div>








        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.3"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.3"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.3"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.3"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.3"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.3"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.3"></script>



  


  




	





  





  








  <link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">
  <script src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>
  <div id="gitalk-container"></div>
  <script type="text/javascript">
    var gitalk = new Gitalk({
      clientID: '539ee569f1e8cf3ea34a',
      clientSecret: 'd4384d3c96e794fea423f52d48aec0caab7d0eea',
      repo: 'blog_comment',
      owner: 'TheBigFish',
      admin: ['TheBigFish'],
      id: location.pathname,
      distractionFreeMode: 'false'
    })
    gitalk.render('gitalk-container')
  </script>



  





  

  

  

  

  

  

</body>
</html>
